﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Ria.Data;
using System.Windows.Shapes;
using GraphInformation;

namespace CARE.Views
{
    public partial class ModelEditor : ChildWindow
    {
        private NewElement elementPopup = new NewElement();
        private NewEdge edgePopup = new NewEdge();
        private ExportModel exportPopup = new ExportModel();
        private Brush normalBrush = new SolidColorBrush(Colors.Black);
        private Brush highlightedBrush = new SolidColorBrush(Colors.Yellow);
        private Boolean isMouseCaptured = false;
        private double mouseVerticalPosition;
        private double mouseHorizontalPosition;
        private Boolean isDrawingConnection = false;
        private double StartMouseVerticalPosition;
        private double StartMouseHorizontalPosition;

        private Connector lastConector;
        //private ModelEdge lineCanvas;
        //private ModelNode StartNode;
        private Canvas SelectedElement;
        private Graph graph = new Graph();

        public ModelEditor()
        {
            InitializeComponent();
            graph.ID = Guid.NewGuid();
            elementPopup.Closed += new EventHandler(elementPopup_Closed);
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        private void Save_Click(object sender, RoutedEventArgs e)
        {

        }

        private void Remove_Click(object sender, RoutedEventArgs e)
        {

        }

        private void CreateNode_Click(object sender, RoutedEventArgs e)
        {
            elementPopup.Show();
            
            
        }

        void elementPopup_Closed(object sender, EventArgs e)
        {
            if (elementPopup.DialogResult.GetValueOrDefault())
            {
                int selectorHeight = 5;
                int selectorWidth = 5;

                Canvas RectWithTitle = CreateRectangleWithTitle(elementPopup.NodeName, elementPopup.NodeColor);
                Canvas selectorCanvasLeft = CreateConnector(selectorHeight, selectorWidth);
                Canvas selectorCanvasRight = CreateConnector(selectorHeight, selectorWidth);
                Canvas selectorCanvasTop = CreateConnector(selectorHeight, selectorWidth);
                Canvas selectorCanvasBootom = CreateConnector(selectorHeight, selectorWidth);

                RectWithTitle.SetValue(Canvas.LeftProperty, selectorCanvasLeft.Width / 2.0);
                RectWithTitle.SetValue(Canvas.TopProperty, selectorCanvasLeft.Height / 2.0);

                selectorCanvasLeft.SetValue(Canvas.LeftProperty, 0.0);
                selectorCanvasLeft.SetValue(Canvas.TopProperty, RectWithTitle.Height / 2.0);

                selectorCanvasRight.SetValue(Canvas.LeftProperty, RectWithTitle.Width);
                selectorCanvasRight.SetValue(Canvas.TopProperty, RectWithTitle.Height / 2.0);

                selectorCanvasTop.SetValue(Canvas.LeftProperty, RectWithTitle.Width / 2.0);
                selectorCanvasTop.SetValue(Canvas.TopProperty, 0.0);

                selectorCanvasBootom.SetValue(Canvas.LeftProperty, RectWithTitle.Width / 2.0);
                selectorCanvasBootom.SetValue(Canvas.TopProperty, RectWithTitle.Height);

                GraphLayout.GraphRepresentation.NodeItem element = new GraphLayout.GraphRepresentation.NodeItem()
                {
                    Width = RectWithTitle.Width + selectorWidth,
                    Height = RectWithTitle.Height + selectorHeight
                };

                //element.border = RectWithTitle.Children[0] as Rectangle;

                //TODO:
                element.MouseLeftButtonDown += new MouseButtonEventHandler(Handle_MouseDown);
                element.MouseLeftButtonUp += new MouseButtonEventHandler(Handle_MouseUp);
                element.MouseMove += new MouseEventHandler(Handle_MouseMove);

                element.Children.Add(RectWithTitle);
                element.Children.Add(selectorCanvasLeft);
                element.Children.Add(selectorCanvasRight);
                element.Children.Add(selectorCanvasTop);
                element.Children.Add(selectorCanvasBootom);
                //
                //                element.connectors.Add(selectorCanvasLeft as Connector);
                //                element.connectors.Add(selectorCanvasRight as Connector);
                //                element.connectors.Add(selectorCanvasTop as Connector);
                //                element.connectors.Add(selectorCanvasBootom as Connector);

                element.SetValue(Canvas.LeftProperty, this.Width / 2.0 - element.Width);
                element.SetValue(Canvas.TopProperty, this.Height / 2.0 - element.Height);


                var node = new GraphInformation.GraphElement() { ID = Guid.NewGuid(), GraphID = graph.ID };
                node.Keys.Add(new PairKeyValue() { Key = "stateName", Value = elementPopup.NodeName });
                node.Keys.Add(new PairKeyValue() { Key = "stateClass", Value = elementPopup.StateClass });
                node.Keys.Add(new PairKeyValue() { Key = "nodeColor", Value = elementPopup.NodeColor.ToString() });
                node.Keys.Add(new PairKeyValue() { Key = "nodeX", Value = element.GetValue(Canvas.LeftProperty).ToString() });
                node.Keys.Add(new PairKeyValue() { Key = "nodeY", Value = element.GetValue(Canvas.TopProperty).ToString() });
                graph.Vertices.Add(node);

                //                element.node = node;
                //
                //                if (popup.StartState.IsChecked.HasValue)
                //                {
                //                    if (popup.StartState.IsChecked.Value)
                //                        StartState = popup.NodeName;
                //                }

                rootCanvas.Children.Add(element);
            }
        }

        private void exportToDatabase_Click(object sender, RoutedEventArgs e)
        {
            exportPopup.Show();
        }

        public Canvas CreateRectangleWithTitle(String name, Color color)
        {
            LinearGradientBrush myHorizontalGradient = GetGradient(color);
            Brush projBrush = myHorizontalGradient;

            Brush textColor = new SolidColorBrush(Colors.Black);
            TextBlock title = new TextBlock()
            {
                Foreground = textColor,
                Text = name,
                FontSize = 12
            };

            double Height = 25d;
            double Width = (title.ActualWidth + 4) < Height ? Height : title.ActualWidth + 4;
            Width += 4;

            Canvas RectWithTitle = new Canvas()
            {
                Width = Width,
                Height = Height
            };

            Rectangle nodeBkg = new Rectangle()
            {
                Width = Width,
                Height = Height,
                Fill = projBrush,
                Stroke = normalBrush
            };

            nodeBkg.RadiusX = 10;
            nodeBkg.RadiusY = 10;

            RectWithTitle.Children.Add(nodeBkg);
            RectWithTitle.Children.Add(title);

            double left = (nodeBkg.Width - title.ActualWidth) / 2;
            double top = (nodeBkg.Height - title.ActualHeight) / 2;
            title.SetValue(Canvas.LeftProperty, left);
            title.SetValue(Canvas.TopProperty, top);

            return RectWithTitle;
        }

        private static LinearGradientBrush GetGradient(Color second)
        {
            GradientStopCollection GradientStops = new GradientStopCollection();
            LinearGradientBrush myHorizontalGradient = new LinearGradientBrush();
            myHorizontalGradient.StartPoint = new Point(0.5, 0);
            myHorizontalGradient.EndPoint = new Point(0.5, 1);
            myHorizontalGradient.GradientStops.Add(new GradientStop()
            {
                Color = second,
                Offset = 1.0
            });
            myHorizontalGradient.GradientStops.Add(new GradientStop()
            {
                Color = Colors.White,
                Offset = 0.1
            });
            return myHorizontalGradient;
        }

        private Connector CreateConnector(int selectorHeight, int selectorWidth)
        {
            Connector selectorCanvas = new Connector()
            {
                Height = selectorHeight,
                Width = selectorWidth
            };
            Border selectorBorder = new Border()
            {
                Width = selectorWidth,
                Height = selectorHeight,
                BorderThickness = new Thickness(1),
                BorderBrush = new SolidColorBrush(Colors.Black)
            };
            Line selectorHorizontalLine = new Line()
            {
                Stroke = new SolidColorBrush(Colors.Black),
                StrokeThickness = 1.0,
                X1 = 1.0,
                X2 = selectorHeight - 1.0,
                Y1 = selectorWidth / 2.0,
                Y2 = selectorWidth / 2
            };

            Line selectorVerticallLine = new Line()
            {
                Stroke = new SolidColorBrush(Colors.Black),
                StrokeThickness = 1.0,
                X1 = selectorHeight / 2.0,
                X2 = selectorHeight / 2.0,
                Y1 = 1.0,
                Y2 = selectorWidth - 1.0
            };
            selectorCanvas.Children.Add(selectorBorder);
            selectorCanvas.Children.Add(selectorHorizontalLine);
            selectorCanvas.Children.Add(selectorVerticallLine);

            //TODO:
            //selectorCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(selectorCanvas_MouseLeftButtonDown);
            //selectorCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(selectorCanvas_MouseLeftButtonUp);
            //selectorCanvas.MouseEnter += new MouseEventHandler(selectorCanvas_MouseEnter);
            //selectorCanvas.MouseLeave += new MouseEventHandler(selectorCanvas_MouseLeave);

            return selectorCanvas;
        }

        #region Nodes events
        void Handle_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!isDrawingConnection)
            {
                GraphLayout.GraphRepresentation.NodeItem item = sender as GraphLayout.GraphRepresentation.NodeItem;

                RemoveHighlight();

                SelectedElement = item;
                GraphLayout.GraphRepresentation.NodeItem model = SelectedElement as GraphLayout.GraphRepresentation.NodeItem;
               // model.border.Stroke = highlightedBrush;

                mouseVerticalPosition = e.GetPosition(null).Y;
                mouseHorizontalPosition = e.GetPosition(null).X;
                isMouseCaptured = true;
                item.CaptureMouse();
            }

        }

        void Handle_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!isDrawingConnection)
            {
                Canvas item = sender as Canvas;
                isMouseCaptured = false;
                item.ReleaseMouseCapture();
                mouseVerticalPosition = -1;
                mouseHorizontalPosition = -1;
            }

        }

        void Handle_MouseMove(object sender, MouseEventArgs e)
        {
            Canvas item = sender as Canvas;

            if (isMouseCaptured && !isDrawingConnection)
            {

                // Calculate the current position of the object.
                double deltaV = e.GetPosition(null).Y - mouseVerticalPosition;
                double deltaH = e.GetPosition(null).X - mouseHorizontalPosition;
                double newTop = deltaV + (double)item.GetValue(Canvas.TopProperty);
                double newLeft = deltaH + (double)item.GetValue(Canvas.LeftProperty);

                if (item is GraphLayout.GraphRepresentation.NodeItem)
                {
                    ((GraphLayout.GraphRepresentation.NodeItem)item).X = (float)newLeft;
                    ((GraphLayout.GraphRepresentation.NodeItem)item).Y = (float)newTop;
                }

                foreach (var child in item.Children)
                {
                    if (child is Connector)
                    {
                        Connector connector = child as Connector;
                        foreach (var pair in connector.lines)
                        {
                            var canvas = pair.Key;

                            //canvas.Height += deltaV;
                            //canvas.Width += deltaH;

                            //TODO:
                            Line line = new Line();//canvas.line;

                            double x1 = (double)item.GetValue(Canvas.LeftProperty);
                            double x2 = x1 + item.Width;
                            double y1 = (double)item.GetValue(Canvas.TopProperty);
                            double y2 = y1 + item.Height;

                            if (pair.Value)
                            {
                                line.X2 += deltaH;
                                line.Y2 += deltaV;
                            }
                            else
                            {
                                line.X1 += deltaH;
                                line.Y1 += deltaV;
                            }

                            StartMouseHorizontalPosition = line.X1;
                            StartMouseVerticalPosition = line.Y1;
                            mouseHorizontalPosition = line.X2;
                            mouseVerticalPosition = line.Y2;
                            Point l1;
                            Point l2;
//                            GetArrow(out l1, out l2);
//
//                            canvas.lineArrow.Points.Clear();
//                            //TODO: arrow
//                            canvas.lineArrow.Points.Add(new Point(mouseHorizontalPosition, mouseVerticalPosition));
//                            canvas.lineArrow.Points.Add(new Point(l1.X, l1.Y));
//                            canvas.lineArrow.Points.Add(new Point(l2.X, l2.Y));
                        }
                    }
                }

                // Set new position of object.
                item.SetValue(Canvas.TopProperty, newTop);
                item.SetValue(Canvas.LeftProperty, newLeft);

                // Update position global variables.
                mouseVerticalPosition = e.GetPosition(null).Y;
                mouseHorizontalPosition = e.GetPosition(null).X;
            }
//            if (isDrawingConnection)
//            {
//                if (lineCanvas == null)
//                {
//
//                    var line = new Line
//                    {
//                        X1 = StartMouseHorizontalPosition,
//                        Y1 = StartMouseVerticalPosition,
//                        X2 = mouseHorizontalPosition,
//                        Y2 = mouseVerticalPosition,
//                        Stroke = new SolidColorBrush(Colors.Black),
//                        StrokeThickness = 3
//                    };
//
//
//
//                    Polygon lineArrow = new Polygon();
//                    lineArrow.Points = new PointCollection();
//                    lineArrow.Fill = new SolidColorBrush(Colors.Black);
//                    Point l1;
//                    Point l2;
//                    GetArrow(out l1, out l2);
//
//                    //TODO: arrow
//                    lineArrow.Points.Add(new Point(mouseHorizontalPosition, mouseVerticalPosition));
//                    lineArrow.Points.Add(new Point(l1.X, l1.Y));
//                    lineArrow.Points.Add(new Point(l2.X, l2.Y));
//
//                    lineCanvas = new ModelEdge()
//                    {
//                        Height = line.Height,
//                        Width = line.Width
//                    };
//
//                    lineCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(lineCanvas_MouseLeftButtonDown);
//
//                    lineCanvas.line = line;
//                    lineCanvas.lineArrow = lineArrow;
//
//                    lineCanvas.Children.Add(line);
//                    lineCanvas.Children.Add(lineArrow);
//                    rootCanvas.Children.Add(lineCanvas);
//
//                    lastConector.lines.Add(lineCanvas, false);
//                }
//                else
//                {
//                    lineCanvas.line.X2 = mouseHorizontalPosition;
//                    lineCanvas.line.Y2 = mouseVerticalPosition;
//
//                    Point l1;
//                    Point l2;
//                    GetArrow(out l1, out l2);
//
//
//                    lineCanvas.lineArrow.Points.Clear();
//                    //TODO: arrow
//                    lineCanvas.lineArrow.Points.Add(new Point(mouseHorizontalPosition, mouseVerticalPosition));
//                    lineCanvas.lineArrow.Points.Add(new Point(l1.X, l1.Y));
//                    lineCanvas.lineArrow.Points.Add(new Point(l2.X, l2.Y));
//
//                    lineCanvas.Height = lineCanvas.line.Height;
//                    lineCanvas.Width = lineCanvas.line.Width;
//                }
//
//                mouseVerticalPosition = e.GetPosition(rootCanvas).Y;
//                mouseHorizontalPosition = e.GetPosition(rootCanvas).X;
//
//
//            }
        }

        #endregion

        private void RemoveHighlight()
        {
            if (SelectedElement != null)
            {
                if (SelectedElement is GraphLayout.GraphRepresentation.NodeItem)
                {
                    //ModelNode model = SelectedElement as ModelNode;
                    //model.border.Stroke = normalBrush;
                }
                if (SelectedElement is GraphLayout.GraphRepresentation.EdgeItem)
                {
                    //LIne
                   // ModelEdge item = SelectedElement as ModelEdge;
                   // Line line = item.line;
                   // line.Stroke = normalBrush;
                }
            }
        }
    }
}

